package controllers

import (
	"encoding/json"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/httplib"
	log "github.com/astaxie/beego/logs"
	"i-hea.com/ttsc/kdxf"
	"i-hea.com/ttsc/ttsclient"
	"i-hea.com/utils/models"
	"strings"
	"sync"
	"time"
)

type MainController struct {
	beego.Controller
}

const (
	brandWebank = "webank"
)

var (
	appInfo    sync.Map
	SignServer string
)

func (this *MainController) URLMapping() {
	this.Mapping("convert", this.ConvertKdxfTts)
	this.Mapping("convertv2", this.ConvertTts)
	this.Mapping("convertAliTts", this.ConvertAliTts)
	this.Mapping("convertFlowTts", this.ConvertFlowTts)
	this.Mapping("convertPreFlowTts", this.ConvertPreTts)

}

// @Title 阿里tts转换
// @Description
// @Param   text      formData   string    true      "需要转换的tts"
// @Param   AppId    formData   string    true      "企业id"
// @Success 200 {object}   controllers.Result        ""
// @Failure 400
// @Failure 404
// @router /convertAliTts [post]
func (this *MainController) ConvertAliTts() {

	type param struct {
		Args  map[string]interface{} `json:"args"`
		AppId string                 `json:"appid"`
	}

	var ob param
	err := json.Unmarshal(this.Ctx.Input.RequestBody, &ob)
	if err != nil {
		log.Error("param is not json", string(this.Ctx.Input.RequestBody))
		this.Data["json"] = &ERROR_PARAM_NOT_JSON
		this.ServeJSON()
		return
	}

	text, ok := ob.Args["text"]
	if !ok {
		log.Error("text is nil", string(this.Ctx.Input.RequestBody))
		this.Data["json"] = &ERROR_PARAM_INVALID
		this.ServeJSON()
		return
	}

	ttsText := text.(string)
	log.Debug("recv ali tts convert:%v", ttsText)
	file, err := ttsclient.NewAliTTSTask(ttsText, ob.AppId)
	if err == nil {
		this.Data["json"] = &Result{0, file}
	} else {
		this.Data["json"] = &Result{-1, err.Error()}
	}

	this.ServeJSON()
	return
}

// @Title
// @Description
// @Param   args     formData   []byte    true      "需要转换的tts参数"
// @Param   AppId    formData   string    true      "企业id"
// @Success 200 {object}   controllers.Result        ""
// @Failure 400
// @Failure 404
// @router /convertv2 [post]
func (this *MainController) ConvertTts() {

	type param struct {
		Args  map[string]interface{} `json:"args"`
		AppId string                 `json:"appid"`
	}

	var ob param
	err := json.Unmarshal(this.Ctx.Input.RequestBody, &ob)
	if err != nil {
		log.Error("param is not json", string(this.Ctx.Input.RequestBody))
		this.Data["json"] = &ERROR_PARAM_NOT_JSON
		this.ServeJSON()
		return
	}

	log.Debug("recv  tts convert:%v", ob.Args)

	file, err := ttsclient.NewTecnentConvertTask(ob.AppId, ob.Args)
	if err == nil {
		this.Data["json"] = &Result{0, file}
	} else {
		this.Data["json"] = &Result{-1, err.Error()}
	}

	this.ServeJSON()
	return
}

// @Title 腾讯流式转换tts
// @Description  腾讯流式转换tts
// @Param   args     formData   []byte    true      "需要转换的tts参数"
// @Param   AppId    formData   string    true      "企业id"
// @Success 200 {object}   controllers.Result        ""
// @Failure 400
// @Failure 404
// @router /convertFlowTts [post]
func (this *MainController) ConvertFlowTts() {

	type param struct {
		Args  map[string]interface{} `json:"args"`
		AppId string                 `json:"appid"`
	}

	var ob param
	err := json.Unmarshal(this.Ctx.Input.RequestBody, &ob)
	if err != nil {
		log.Error("param is not json:%v,err:%v", string(this.Ctx.Input.RequestBody), err)
		this.Data["json"] = &ERROR_PARAM_NOT_JSON
		this.ServeJSON()
		return
	}

	log.Debug("recv  tts convert:%v", ob.Args)
	file, err := ttsclient.NewTecnentConvertTask(ob.AppId, ob.Args)
	if err == nil {
		this.Data["json"] = &Result{0, file}
	} else {
		this.Data["json"] = &Result{109201, err.Error()}
	}

	this.ServeJSON()
	return
}

var errCount int = 0

// @router /convertPreFlowTts [post]
func (this *MainController) ConvertPreTts() {

	type param struct {
		Args      map[string]interface{} `json:"args"`
		AppId     string                 `json:"appId"`
		RequestId string                 `json:"requestId"`
	}

	var ob param
	err := json.Unmarshal(this.Ctx.Input.RequestBody, &ob)
	if err != nil {
		log.Error("param is not json:%v,err:%v", string(this.Ctx.Input.RequestBody), err)
		this.Data["json"] = &ERROR_PARAM_NOT_JSON
		this.ServeJSON()
		return
	}

	go func() {

		type ttsResponse struct {
			Event       string `json:"event"`
			RequestId   string `json:"requestId"`
			Code        string `json:"code"`
			TtsErrorMsg string `json:"ttsErrorMsg"`
		}

		result := ttsResponse{
			Event:       "preTtsResult",
			Code:        "000000",
			TtsErrorMsg: "success",
			RequestId:   ob.RequestId,
		}

		start := time.Now()
		log.Debug("[%v]recv  tts convert:%v", ob.RequestId, ob.Args)
		ttsType, ok := ob.Args["engineType"]
		if ok {
			if ttsType == "ttsEngineQcloud" {

				_, err = ttsclient.NewTecnentPreConvertTask(ob.Args)
				if err != nil {
					result.Code = "109201"
					result.TtsErrorMsg = err.Error()
					if strings.HasPrefix(err.Error(), "open") {
						errCount++ //os.Exit(1)
						if errCount > 100 {
							panic(err.Error())
						}
					}
				}
			} else {
				//科大讯飞
				_, err := kdxf.ConvertTTS(ob.Args)
				if err != nil {
					result.Code = "109201"
					result.TtsErrorMsg = err.Error()
				}
			}
		} else {
			//科大讯飞
			_, err := kdxf.ConvertTTS(ob.Args)
			if err != nil {
				result.Code = "109201"
				result.TtsErrorMsg = err.Error()
			}
		}

		if nil != err {
			log.Debug("[%v]result:%v", ob.RequestId, err.Error())
		}

		app, ok := appInfo.Load(ob.AppId)
		if !ok {
			ap, err := models.GetAppsByAppid(ob.AppId)
			if err != nil {
				log.Error("[%v]get app[%v] info failed:%v", ob.RequestId, ob.AppId, err)
				return
			}

			appInfo.Store(ob.AppId, ap)
			app = ap
		}

		repData, _ := json.Marshal(result)
		reqUrl := app.(*models.IpccAppInfo).CallAddress
		if app.(*models.IpccAppInfo).Brand == brandWebank && SignServer != "" {

			/* 新增鉴权 */
			type SignMsg struct {
				HttpUrl string `json:"httpUrl"`
				Data    []byte `json:"httpBody"`
				Brand   string `json:"brand"`
			}

			newReq := SignMsg{
				HttpUrl: app.(*models.IpccAppInfo).CallAddress,
				Data:    repData,
				Brand:   app.(*models.IpccAppInfo).Brand,
			}

			repData, _ = json.Marshal(newReq)
			reqUrl = SignServer
		}
		req := httplib.Post(reqUrl)
		wbResp, err := req.Body(repData).
			SetTimeout(5*time.Second, 5*time.Second).
			String()
		if err != nil {
			log.Error("[%v]send convert response failed:%v", ob.RequestId, err)
			if strings.HasPrefix(err.Error(), "open") {
				errCount++ //os.Exit(2)
				if errCount > 100 {
					panic(err.Error())
				}
			}
		}
		log.Debug("[%v]request[%v] response:%v, cost:[%v] err:%v",
			ob.RequestId, ob.Args, string(wbResp), time.Since(start), err)
	}()

	this.Data["json"] = &SUCCESS
	this.ServeJSON()

	return
}

// @Title 阿里tts转换
// @Description
// @Param   text      formData   string    true      "需要转换的tts"
// @Param   AppId    formData   string    true      "企业id"
// @Success 200 {object}   controllers.Result        ""
// @Failure 400
// @Failure 404
// @router /convert [post]
func (this *MainController) ConvertKdxfTts() {

	type param struct {
		Args  map[string]interface{} `json:"args"`
		AppId string                 `json:"appid"`
	}

	var ob param
	err := json.Unmarshal(this.Ctx.Input.RequestBody, &ob)
	if err != nil {
		log.Error("param is not json", string(this.Ctx.Input.RequestBody))
		this.Data["json"] = &ERROR_PARAM_NOT_JSON
		this.ServeJSON()
		return
	}

	text, ok := ob.Args["text"]
	if !ok {
		log.Error("text is nil", string(this.Ctx.Input.RequestBody))
		this.Data["json"] = &ERROR_PARAM_INVALID
		this.ServeJSON()
		return
	}

	ttsText := text.(string)
	log.Debug("recv kdxf tts convert:%v", ttsText)
	file, err := kdxf.AddNewConvertTTSTask(ttsText)
	if err == nil {
		this.Data["json"] = &Result{0, file}
	} else {
		this.Data["json"] = &Result{-1, err.Error()}
	}

	this.ServeJSON()
	return
}
